// 定义消息组件
import {
    BaseElement, ChatStatus, baseStyle
} from "./base.js";


class ChatMessage extends BaseElement {
    constructor() {
        super();
        this.attachShadow({
            mode: 'open'
        });
        this.shadowRoot.adoptedStyleSheets = [baseStyle];

        // 初始化思考过程相关属性
        this.thinkingProcesses = [];
        this.thinkingVisible = false;
        this.totalThinkingDuration = 0;
        this.currentRound = 0;
        this.thinkingContainer = null;
    }

    connectedCallback() {
    }

    // 组件销毁时清理定时器
    disconnectedCallback() {
        if (this.mdRenderTimer) {
            clearTimeout(this.mdRenderTimer);
            this.mdRenderTimer = null;
        }
        if (this.htmlRenderTimer) {
            clearTimeout(this.htmlRenderTimer);
            this.htmlRenderTimer = null;
        }
    }

    container = null; //消息内容dom
    flag = null; //消息标志,也会作为事件的id
    id = null;
    role = null; //消息角色
    startTipShown = true; //是否显示思考中的提示
    finish = false; //是否完成

    hasRendered = false;
    renderTimer = null;
    msgCache = [];
    fragment = null; //markdown渲染用的片段
    refers = null;
    refersExpand = false; //是否展开显示参考信息

    /**
     * 当前正在渲染的类型
     * @type {null}
     */
    renderingType = null;

    lastRenderTime = Date.now();

    /**
     * 当前正在渲染的容器
     * @type {null}
     */
    renderingContainer = null;

    renderingContent = "";

    /**
     * 通知消息完成
     */
    notifyFinish() {
        this.finish = true;
        if (this.messageActions && this.id) {
            this.messageActions.style.display='block'
            this.shadowRoot.querySelector(".msg-tips-box").classList.remove("hide")
        }
        this.scrollToBottom();
    }

    /**
     * 同步数据库数据相关信息
     * @param data
     */
    syncDbData(data) {
        this.id = data.id;
        this.shadowRoot.querySelector('#time').textContent = data.createTime.substring(0, 16);
        console.debug("同步后端数据", this.id)
    }

    /**
     * 生成操作按钮HTML
     */
    generateActionButtons() {
        if (this.role !== 'assistant') return '';

        return `
            <div class="message-actions" style="display: none">
                <button class="message-action-btn copy" data-action="copy" title="复制消息">
                    <svg  viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"  width="12" height="12">
                        <path fill="#94a3b8" d="M480 0h248.2C753.6 0 778 10.2 796 28.2L931.8 164c18 18 28.2 42.4 28.2 67.8V672c0 53-43 96-96 96H480c-53 0-96-43-96-96V96c0-53 43-96 96-96zM160 256h160v128H192v512h384v-64h128v96c0 53-43 96-96 96H160c-53 0-96-43-96-96V352c0-53 43-96 96-96z" p-id="29254" ></path>
                    </svg>
                </button>
                <button class="message-action-btn delete error" data-action="delete" title="删除消息">
                    <svg viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" width="12" height="12">
                        <path fill="#94a3b8" d="M857.2 167.6c22.4 0 41.2 3.6 55.6 11.2 14.8 7.6 26.4 16.8 34.8 28 8.8 11.2 14.8 23.2 18 36.4 3.2 13.2 5.2 25.2 5.2 36.4 0 5.2 0 9.2-0.4 12.4-0.4 2.8-0.4 5.6-0.4 8l0 6.8-74.4 0 0 587.2c0 14.8-2.8 29.2-9.2 43.2-6 13.6-14.8 26-26 36.4-11.2 10.4-24.8 18.8-41.2 25.2-16 6.4-34.8 9.6-55.6 9.6L262.4 1008.4c-19.6 0-38-2.8-55.2-8.8-17.2-6-32-14.4-44.4-25.2-12.4-10.8-22-24-29.2-39.2-7.2-15.2-10.8-32.8-10.8-52l0-576L52.8 307.2c-0.8-0.8-1.2-2.8-1.2-5.6-0.8-3.6-1.2-15.2-1.2-34.8 0-9.6 2.4-20.4 6.8-32.4 4.4-12 11.2-22.8 20.4-32.8 9.2-10 20.8-18.4 34.8-25.2 14.4-6.8 31.2-10 50.8-10l100 0L263.2 97.2c0-19.2 6.8-36 20.4-49.6 13.6-13.6 30-20.8 49.6-20.8l352 0c26.4 0 44.4 6.8 54.4 20.8 10 13.6 15.2 30.4 15.2 49.6l0 69.2c15.6 0.8 32.8 1.2 50.8 1.2L857.2 167.6 857.2 167.6 857.2 167.6zM333.2 167.6l352 0L685.2 97.2l-352 0L333.2 167.6 333.2 167.6zM298.4 875.6c24 0 36-15.2 36-46L334.4 310.8 264.4 310.8l0 518.8c0 15.6 2.4 27.2 7.2 34.8C276.8 871.6 285.6 875.6 298.4 875.6L298.4 875.6 298.4 875.6zM510.8 874.4c12.8 0 21.2-3.6 26-10.8 4.4-7.2 6.8-18.4 6.8-34L543.6 310.8l-69.6 0 0 518.8C473.6 859.6 486 874.4 510.8 874.4L510.8 874.4 510.8 874.4zM722.4 872c13.6 0 22.4-3.6 26.8-10.8 4.4-7.2 6.8-18.4 6.8-34L756 310.8l-70.8 0 0 516.4C685.2 857.2 697.6 872 722.4 872L722.4 872 722.4 872z"  p-id="31426"></path>
                    </svg>
                </button>
                <button class="message-action-btn regenerate" data-action="regenerate" title="重新生成">
                    <svg t="1740386672644" class="icon" viewBox="0 0 1211 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="6334" width="12" height="12"><path d="M605.090909 930.909091c-144.616727 0-272.104727-73.309091-347.415273-184.738909L149.643636 746.170182C234.682182 911.173818 406.714182 1024 605.090909 1024c267.077818 0 486.4-204.520727 509.905455-465.454545L1210.181818 558.545455l-139.636364-186.181818-139.636364 186.181818 90.530909 0C998.306909 768 820.736 930.909091 605.090909 930.909091z" p-id="6335" fill="#94a3b8"></path><path d="M605.090909 0C354.117818 0 145.314909 180.596364 101.515636 418.909091L0 418.909091l139.636364 186.181818 139.636364-186.181818L196.561455 418.909091C238.871273 232.354909 405.736727 93.090909 605.090909 93.090909c125.998545 0 238.964364 55.621818 315.764364 143.639273l17.966545-4.608 95.045818 0C942.452364 92.346182 784.570182 0 605.090909 0z" p-id="6336" fill="#94a3b8"></path></svg>
                </button>
            </div>`;
    }

    /**
     * 注册操作事件
     */
    registerActionEvents() {
        const copyBtn = this.shadowRoot.querySelector(".message-action-btn.copy");
        if (copyBtn) {
            copyBtn.addEventListener('pointerdown', () => {
                if (this.container) {
                    const text = this.container.innerText;
                    this.copyText(text)
                }
            });
        }
        const delBtn = this.shadowRoot.querySelector(".message-action-btn.delete");
        if (delBtn) {
            // 为每个按钮添加点击事件监听器
            delBtn.addEventListener('pointerdown', () => {
                // console.debug("开始删除", this.flag, this.id);
                // this.chatInstance.deleteMsg(this.flag, this.id)
                // 显示模态框
                const confirmationModal = this.shadowRoot.querySelector('#confirmationModal');
                if (confirmationModal) { // 确保模态框存在
                    confirmationModal.style.display = 'block';
                }

                // 获取确认按钮并添加事件监听器
                const confirmDeleteBtn = this.shadowRoot.querySelector('#confirmDelete');
                if (confirmDeleteBtn) { // 确保按钮存在
                    confirmDeleteBtn.onclick = () => {
                        console.log('执行删除操作...');
                        // 执行删除操作后，隐藏模态框
                        if (confirmationModal) {
                            confirmationModal.style.display = 'none';
                        }
                        // 删除逻辑
                        console.debug("开始删除", this.flag, this.id);
                        this.chatInstance.deleteMsg(this.flag, this.id);
                    };
                }

                // 获取取消按钮并添加事件监听器
                const cancelDeleteBtn = this.shadowRoot.querySelector('#cancelDelete');
                if (cancelDeleteBtn) { // 确保按钮存在
                    cancelDeleteBtn.onclick = () => {
                        // 隐藏模态框
                        if (confirmationModal) {
                            confirmationModal.style.display = 'none';
                        }
                    };
                }
            });
        }
        const againBtn = this.shadowRoot.querySelector(".message-action-btn.regenerate");
        if (againBtn) {
            againBtn.addEventListener('pointerdown', () => {
                this.chatInstance.regenerate(this.flag, this.id);
            });
        }

        const refersHeader = this.shadowRoot.querySelector(".refers_header");
        refersHeader.addEventListener('pointerdown', () => {
            if (this.refersExpand) {
                this.refers.classList.remove("expand");
            } else {
                this.refers.classList.add("expand");
            }
            this.refersExpand = !this.refersExpand;
        })

        this.registerResizeEvent();

        // 注册思考过程展开/折叠按钮事件
        const thinkingToggleBtn = this.shadowRoot.querySelector('.thinking-toggle');
        if (thinkingToggleBtn) {
            thinkingToggleBtn.addEventListener('click', () => this.toggleThinking());
        }

        // 注册图片的点击事件
        this.shadowRoot.addEventListener('click', (e) => {
            if (e.target.tagName === 'IMG') {
                const src = e.target.src;
                this.previewImg(src);
            } else if (e.target.tagName === 'A') {
                e.preventDefault();
                // 获取链接的href属性
                const url = e.target.getAttribute('href');

                // 检查url是否存在且不为空
                if (url && url.includes("#") == false && url !== 'javascript:void(0)') {
                    // 在新标签页中打开链接
                    window.open(url, '_blank');
                }
            }
        })

    }


    previewImg(src) {
        // Create overlay for the preview
        const overlay = document.createElement('div');
        overlay.className = 'image-preview-overlay';
        overlay.style.cssText = `
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background-color: rgba(0, 0, 0, 0.8);
            display: flex;
            justify-content: center;
            align-items: center;
            z-index: 9999999 !important;
            cursor: pointer;
          `;

        // Create container for the enlarged image
        const container = document.createElement('div');
        container.className = 'image-preview-container';
        container.style.cssText = `
            position: relative;
            max-width: 90%;
            max-height: 90%;
            animation: fadeIn 0.3s;
          `;

        // Create the enlarged image element
        const previewImage = document.createElement('img');
        previewImage.className = 'image-preview-image';
        previewImage.src = src;
        previewImage.style.cssText = `
            max-width: 80vw;
            max-height: 80vh;
            object-fit: contain;
            box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5);
          `;

        // Create close button
        const closeButton = document.createElement('button');
        closeButton.className = 'image-preview-close';
        closeButton.innerHTML = '&times;';
        closeButton.style.cssText = `
            position: absolute;
            top: -40px;
            right: 0;
            background: transparent;
            border: none;
            color: white;
            font-size: 30px;
            cursor: pointer;
          `;
        closeButton.addEventListener('click', () => {
            document.body.removeChild(overlay);
        });
        overlay.addEventListener('click', function(e) {
            if (e.target === overlay) {
                document.body.removeChild(overlay);
            }
        });

        // Add keyframe animation for fade-in effect

        // Append elements to the DOM
        container.appendChild(previewImage);
        container.appendChild(closeButton);
        overlay.appendChild(container);
        document.body.appendChild(overlay);
    }


    /**
     * iframe窗口可以调整大小
     */
    registerResizeEvent() {
        const resizer = this.shadowRoot.querySelector(".resizer");
        if (!resizer) {
            return;
        }
        const curDocument=  this.shadowRoot;
        let startX, startWidth;
        let isResizing = false;
        let enter = false;
        const iframeContainer = this.shadowRoot.querySelector(".container_wrapper");
        const fragment = this.shadowRoot.querySelector(".fragment");
        let exitTimer = null;
        //调整iframe窗口大小

        resizer.addEventListener('mousedown', (e) => {
            e.preventDefault();
            isResizing = true;
            enter = true;
            startX = e.clientX;
            startWidth = parseInt(getComputedStyle(iframeContainer).width, 10);

            // 添加调整中的样式
            resizer.classList.add('active');

            // 添加鼠标移动和松开事件
            curDocument.addEventListener('mousemove', resize);
            curDocument.addEventListener('mouseup', stopResize);
        });

        function resize(e) {
            if (!isResizing) return;

            const newWidth = startWidth + e.clientX - startX;
            // 设置最小宽度限制
            if (newWidth > 100) {
                iframeContainer.style.width = newWidth + 'px';
            }
        }
        // 停止调整大小
        function stopResize() {
            isResizing = false;
            resizer.classList.remove('active');

            curDocument.removeEventListener('mousemove', resize);
            curDocument.removeEventListener('mouseup', stopResize);
            if (exitTimer) {
                clearTimeout(exitTimer);
                exitTimer = null;
            }
        }

        iframeContainer.addEventListener('mouseleave', function() {
            console.debug("离开")
            if (isResizing && enter) {
                enter = false;
                exitTimer = setTimeout(() => {
                    if (!enter) stopResize();
                }, 500)

            }
        });
        iframeContainer.addEventListener('mouseenter', function() {
            enter = true;
            if (exitTimer) {
                clearTimeout(exitTimer);
                exitTimer = null;
            }
        })
        fragment.addEventListener("mouseenter", function (e) {
            e.stopPropagation();
            if (isResizing && enter) {
                enter = false;
                exitTimer = setTimeout(() => {
                    if (!enter) stopResize();
                }, 500)

            }
        })
    }

    copyText(text) {
        // 获取要复制的文本


        // 优先使用 Clipboard API
        if (navigator.clipboard && window.isSecureContext) {
            navigator.clipboard.writeText(text)
                .then(() => {
                    console.debug("文本复制成功", text)
                    this.showNotification();

                })
                .catch(() => this.fallbackCopy(text));
        } else {
            this.fallbackCopy(text);
        }
    }

    // 显示复制成功的提示
    showNotification() {
        const notif = this.shadowRoot.querySelector('#notif');
        if (notif) { // 确保模态框存在
            notif.style.display = 'block';
        }
        setTimeout(function () {
            notif.style.display = 'none';
        }, 3000); // 显示3秒后消失
    }

    fallbackCopy(text) {
        // 创建临时文本区域
        const textArea = document.createElement('textarea');
        textArea.value = text;

        // 设置样式使其不可见
        textArea.style.cssText = `
                position: fixed;
                top: -9999px;
                left: -9999px;
                width: 2em;
                height: 2em;
                padding: 0;
                border: none;
                outline: none;
                box-shadow: none;
                background: transparent;
            `;

        this.shadowRoot.appendChild(textArea);

        // 检查是否是 iOS 设备
        const isIos = navigator.userAgent.match(/ipad|iphone/i);

        if (isIos) {
            // iOS 设备特殊处理
            const range = document.createRange();
            range.selectNodeContents(textArea);
            const selection = window.getSelection();
            selection.removeAllRanges();
            selection.addRange(range);
            textArea.setSelectionRange(0, textArea.value.length);
        } else {
            // 其他设备
            textArea.select();
        }

        try {
            const successful = document.execCommand('copy');
            if (successful) {
                console.debug("文本复制成功", text)
                this.showNotification();

            } else {
                throw new Error('复制命令执行失败');
            }
        } catch (err) {
            console.error('复制失败:', err);
        }

        this.shadowRoot.removeChild(textArea);
    }

    initHtmlRender() {
        return new Promise((resolve, reject) => {
            const iframe = document.createElement('iframe');
            // iframe.style.width = '100vw';
            iframe.sandbox = 'allow-scripts allow-same-origin allow-popups allow-forms';
            iframe.onload = () => {
                const iframeDoc = iframe.contentDocument || iframe.contentWindow.document;

                // 创建基本HTML结构
                iframeDoc.open();
                iframeDoc.write(`
                    <!DOCTYPE html>
                    <html>
                        <head>
                        <script src="/assets/js/tailwind.js"></script>
                        <link rel="stylesheet" href="/assets/fa/css/all.min.css">
                        </head>
                        <body style=""></body>
                    </html>
                `);
                iframeDoc.close();
                // 使用轮询方式检查DOM是否准备好
                const checkBody = () => {
                    if (iframeDoc.body) {
                        this.renderingContainer = iframeDoc.body;
                        resolve()
                        const resizeRo = new ResizeObserver((entries) => {
                            let entry = entries[0];
                            let height = entry.target.scrollHeight;
                            // let width = entry.target.scrollWidth;
                            iframe.style.height = height + 'px';
                            // iframe.style.width = width + 'px';
                        });
                        // 开始监控iframe的body元素:
                        resizeRo.observe(iframeDoc.body);
                    } else {
                        setTimeout(checkBody, 5); // 每10ms检查一次
                    }
                };
                // 开始检查
                checkBody();
            };
            // 立即触发加载
            iframe.src = 'about:blank';
            this.fragment.appendChild(iframe);
        })

    }

    /**
     * 处理AI思考过程
     * @param {Object} msg - 思考过程消息
     * @param {string} msg.status - 状态：START/RUNNING/COMPLETE
     * @param {string} msg.content - 思考内容
     * @param {number} msg.duration - 思考耗时（仅COMPLETE状态有值）
     */
    appendThinking(msg) {
        msg = msg.data;
        // 确保思考容器已初始化
        this.initThinkingContainer();

        // 根据消息状态处理
        switch (msg.status) {
            case 'START':
                this.handleThinkingStart(msg);
                break;
            case 'RUNNING':
                this.handleThinkingRunning(msg);
                break;
            case 'COMPLETE':
                this.handleThinkingComplete(msg);
                break;
        }
    }

    // 初始化思考容器
    initThinkingContainer() {
        if (!this.thinkingContainer) {
            this.thinkingContainer = this.shadowRoot.querySelector('.thinking');
            if (!this.thinkingContainer) return;

            // 确保思考容器可见
            this.thinkingContainer.style.display = 'block';
        }
    }

    // 处理START状态消息
    handleThinkingStart(msg) {
        // 如果上一轮思考已完成，开始新的轮次
        if (this.thinkingProcesses.length > 0 &&
            this.thinkingProcesses[this.thinkingProcesses.length - 1].status === 'COMPLETE') {
            this.currentRound++;
            msg.content = (msg.content ?? '') + '\n\n ----- \n\n';
        }

        msg = {
            status: msg.status,
            content: msg.content??'',
            round: this.currentRound,
            timestamp: Date.now()
        }
        // 存储消息
        this.thinkingProcesses.push(msg);

        // 创建或更新该轮次的条目
        this.createOrUpdateThinkingEntry(msg);

        // 显示思考内容
        this.showThinkingContent();
    }

    // 处理RUNNING状态消息
    handleThinkingRunning(msg) {
        // 如果没有之前的消息，按START处理
        if (this.thinkingProcesses.length === 0) {
            return this.handleThinkingStart(msg);
        }

        // 存储消息
        this.thinkingProcesses[this.thinkingProcesses.length - 1].content += (msg.content??'');

        // 更新该轮次的条目
        this.createOrUpdateThinkingEntry(this.thinkingProcesses[this.thinkingProcesses.length - 1]);
    }

    // 处理COMPLETE状态消息
    handleThinkingComplete(msg) {
        // 如果直接收到COMPLETE状态（非流式）或者在另一个COMPLETE之后
        if (this.thinkingProcesses.length === 0 ||
            this.thinkingProcesses[this.thinkingProcesses.length - 1].status === 'COMPLETE') {

            // 如果不是第一条消息，开始新轮次
            if (this.thinkingProcesses.length > 0) {
                this.currentRound++;
                msg.content = (msg.content ?? '') + '\n\n ----- \n\n';
            }
            msg = {
                status: msg.status,
                content: msg.content,
                duration: msg.duration || 0,
                round: this.currentRound,
                timestamp: Date.now()
            }
            // 存储消息
            this.thinkingProcesses.push(msg);
        } else {
            let item = this.thinkingProcesses[this.thinkingProcesses.length - 1];
            item.content += (msg.content ?? '');
            item.duration = msg.duration || 0;
            msg = item;
        }


        // 创建或更新该轮次的条目
        this.createOrUpdateThinkingEntry(msg);

        // 更新总思考时间
        this.totalThinkingDuration += (msg.duration || 0);

        // 更新时间显示
        this.updateDurationDisplay();

        // COMPLETE后隐藏思考内容
        this.hideThinkingContent();
    }


    // 创建或更新当前轮次的思考条目
    createOrUpdateThinkingEntry(msg) {
        const contentEl = this.thinkingContainer.querySelector('.thinking-content');
        if (!contentEl) return;
        this.hideStartTip();
        if(!msg.container) {

            // 查找或创建该轮次的条目
            let entry = contentEl.querySelector(`.thinking-entry[data-round="${this.currentRound}"]`);

            if (!entry) {
                entry = document.createElement('div');
                entry.className = 'thinking-entry';
                entry.setAttribute('data-round', this.currentRound);
                contentEl.appendChild(entry);
            }
            msg.container = entry;
        }

        // 使用markdown渲染更新条目内容
        if (this.chatInstance.config.onMarkdownRender) {
            msg.container.innerHTML = this.chatInstance.config.onMarkdownRender(msg.content);
        } else {
            msg.container.innerText = msg.content;
        }

        // 滚动到内容底部
        contentEl.scrollTop = contentEl.scrollHeight;
    }

    // 更新思考时间显示
    updateDurationDisplay() {
        const durationEl = this.thinkingContainer.querySelector('.thinking-duration');
        if (!durationEl) return;
        if (this.totalThinkingDuration > 0) {
            durationEl.textContent = ` (${this.formatDuration(this.totalThinkingDuration)})`;
        }
    }

    // 切换思考内容可见性
    toggleThinking() {
        const contentEl = this.thinkingContainer.querySelector('.thinking-content');
        const toggleBtn = this.thinkingContainer.querySelector('.thinking-toggle');
        if (!contentEl || !toggleBtn) return;

        const toggleText = toggleBtn.querySelector('.thinking-toggle-text');
        const toggleIcon = toggleBtn.querySelector('.thinking-toggle-icon');

        if (contentEl.style.display === 'none') {
            contentEl.style.display = 'block';
            if (toggleText) toggleText.textContent = '收起思考过程';
            if (toggleIcon) toggleIcon.style.transform = 'rotate(180deg)';
            this.thinkingVisible = true;
        } else {
            contentEl.style.display = 'none';
            if (toggleText) toggleText.textContent = '展开思考过程';
            if (toggleIcon) toggleIcon.style.transform = 'rotate(0deg)';
            this.thinkingVisible = false;
        }
    }

    // 显示思考容器和内容
    showThinkingContent() {
        if (!this.thinkingContainer) return;

        this.thinkingContainer.style.display = 'block';

        const contentEl = this.thinkingContainer.querySelector('.thinking-content');
        if (contentEl) {
            contentEl.style.display = 'block';
        }

        // 更新切换按钮
        const toggleBtn = this.thinkingContainer.querySelector('.thinking-toggle');
        if (toggleBtn) {
            const toggleText = toggleBtn.querySelector('.thinking-toggle-text');
            const toggleIcon = toggleBtn.querySelector('.thinking-toggle-icon');

            if (toggleText) toggleText.innerHTML = `<div class="start_tip">
                            <span>AI正在思考中</span>
                            <div class="dots">
                                <span></span>
                                <span></span>
                                <span></span>
                            </div>
                        </div>`;
            if (toggleIcon) toggleIcon.style.transform = 'rotate(180deg)';
        }

        this.thinkingVisible = true;
    }

    // 隐藏思考内容但保持容器可见
    hideThinkingContent() {
        if (!this.thinkingContainer) return;

        const contentEl = this.thinkingContainer.querySelector('.thinking-content');
        if (contentEl) {
            contentEl.style.display = 'none';
        }

        // 更新切换按钮
        const toggleBtn = this.thinkingContainer.querySelector('.thinking-toggle');
        if (toggleBtn) {
            const toggleText = toggleBtn.querySelector('.thinking-toggle-text');
            const toggleIcon = toggleBtn.querySelector('.thinking-toggle-icon');

            if (toggleText) toggleText.textContent = '展开思考过程';
            if (toggleIcon) toggleIcon.style.transform = 'rotate(0deg)';
        }

        this.thinkingVisible = false;
    }

    // 格式化毫秒时间为易读字符串
    formatDuration(ms) {
        if (ms < 1000) {
            return `${ms}毫秒`;
        } else if (ms < 60000) {
            return `${(ms / 1000).toFixed(1)}秒`;
        } else {
            const minutes = Math.floor(ms / 60000);
            const seconds = ((ms % 60000) / 1000).toFixed(1);
            return `${minutes}分${seconds}秒`;
        }
    }

    async renderMsg() {
        let msg = this.msgCache.shift();

        if ((!msg && this.finish) || (msg && msg.renderType != this.renderingType && this.renderingType && this.renderingContent)) {
            //没消息或者这次的消息和上次不一样，都需要把之前遗留的处理一下
            switch (this.renderingType) {
                case 'text':
                    this.renderingContainer.innerText += this.renderingContent;
                    break;
                case "markdown":
                    this.renderingContainer.innerHTML = this.chatInstance.config.onMarkdownRender(this.renderingContent);
                    break;
                case "html":
                default:
                    this.renderHtmlMsg(false);
            }
        }

        if (!msg && this.finish) {//没消息了也结束了
            this.renderingType = null;
            this.renderingContent = null;
            this.renderingContainer = null;
            return
        };
        if (!msg) { //没消息了继续等待
            setTimeout(() => {
                this.renderMsg()
            }, 20)
            return;
        }

        if (msg.renderType != this.renderingType) {

            if (msg.renderType == 'markdown' && !this.chatInstance.config.onMarkdownRender) {
                console.warn("未配置markdown渲染函数，无法渲染markdown消息")
                return;
            }
            this.renderingType = msg.renderType || 'text';
            this.renderingContent = "";
            if (this.renderingType == 'html') {
                await this.initHtmlRender();
            } else {
                this.renderingContainer = document.createElement('div');
                this.renderingContainer.classList.add(`md-${msg.role ?? 'assistant'}`);
                this.fragment.appendChild(this.renderingContainer);
            }

        }

        this.renderingContent += msg.content;

        if (this.lastRenderTime + 20 < Date.now() && this.renderingContainer && this.renderingContent) {
            switch (this.renderingType) {
                case 'text':
                    this.renderingContainer.innerText += this.renderingContent;
                    this.renderingContent = '';
                    break;
                case "markdown":
                    this.renderingContainer.innerHTML = this.chatInstance.config.onMarkdownRender(this.renderingContent);
                    break;
                case "html":
                default:
                    this.renderHtmlMsg();
            }
            this.lastRenderTime = Date.now();
            this.scrollToBottom();
        }

        setTimeout(() => {
            this.renderMsg();
        }, 0)


    }

    renderHtmlMsg(ignoreScript=true) {
        const div = document.createElement("div");

        if (!this.renderingContent) {
            return;
        }
        div.innerHTML = this.renderingContent;
        //移除div里的script标签
        const scripts = div.querySelectorAll("script");
        if (ignoreScript) {
            scripts.forEach(script => script.remove());
        } else {
            scripts.forEach(originalScript => {
                // 在iframe中创建新的script元素
                const newScript = this.renderingContainer.ownerDocument.createElement('script');

                // 复制原始脚本的所有属性
                Array.from(originalScript.attributes).forEach(attr => {
                    newScript.setAttribute(attr.name, attr.value);
                });

                // 处理内联脚本（没有src属性的脚本）
                if (!originalScript.src && originalScript.textContent) {
                    newScript.textContent = originalScript.textContent;
                }
                // 将新脚本添加到iframe文档中
                this.renderingContainer.appendChild(newScript);
            });
            this.renderingContainer?.ownerDocument?.dispatchEvent(new Event('DOMContentLoaded'));
        }
        this.renderingContainer.innerHTML = div.innerHTML;
        this.renderingContainer.parentElement.scrollTo({
            top:this.renderingContainer.parentElement.scrollHeight,
            behavior: 'smooth'
        });
    }


    scrollToBottom() {
        this.getRootNode().host.scrollToBottom();
    }

    toJson(str) {
        try {
            const result = JSON.parse(str);

            // 额外检查：确保解析结果是对象或数组
            // 注意：null 也会被 JSON.parse 成功解析，但 typeof null 返回 'object'
            const type = typeof result;
            if( (type === 'object' && result !== null) || Array.isArray(result)) {
                return result;
            }
            return false;

        } catch (e) {
            return false;
        }
    }

    appendMsg(msg) {
        if (!msg.data?.content?.text) {
            return;
        }
        const text = msg.data.content.text;
        const validJson = this.toJson(text);
        if (validJson && validJson[0]?.renderType) {
            //新的消息结构
            const msgs = JSON.parse(text);
            for (let item of msgs) {
                item.role = msg.data.role;
                this.msgCache.push(item)
            }
        } else {
            //历史版本的消息结构，未使用json结构 或者 后端正在动态输入的消息
            this.msgCache.push({
                renderType: msg.data.renderType ?? 'text',
                content: msg.data.content.text,
                role: msg.data.role
            })

        }


    }

    renderReference(refs) {
        if (!refs || !refs.length) {
            return;
        }
        this.refers.classList.remove('hide');
        this.refers.querySelector(".refers_count").innerText=`-${refs.length}`
        refs.forEach(item => {
            const reference = document.createElement('reference-item');
            reference.setAttribute('type', item.type);
            reference.setAttribute('content', item.content);
            reference.setAttribute('url', item.url);
            reference.setAttribute('file-name', item.fileName);
            reference.setAttribute('file-id', item.fileId);
            this.refers.querySelector('.refers_list').appendChild(reference);
        })
    }

    hideStartTip() {
        //追加渲染
        if (this.startTipShown) {
            // 如果已经有内容，移除思考中的提示
            const startTip = this.container.querySelector('.start_tip');
            if (startTip) {
                startTip.remove();
            }
            this.startTipShown = false;
        }
    }

    render(msg) {
        this.id = (this.id || msg.id) || null;
        if (this.hasRendered) {
            this.hideStartTip()
            // 文本内容
            this.appendMsg(msg)
            if (msg.data?.msg) {
                const msgTip = document.createElement('msg-tip');
                msgTip.setAttribute('type', msg.action ?? 'error');
                msgTip.textContent = msg.data.msg;
                this.container.appendChild(msgTip);
            }
            if (msg.action == 'reference' && msg.data) {
                // 参考资料
                //判断msg.data是个对象还是数组
                let list = Array.isArray(msg.data) ? msg.data : [msg.data];
                this.renderReference(list)
            }
            if (msg.data.reference) {
                this.renderReference(msg.data.reference)
            }
            return;
        }
        this.hasRendered = true;

        //判断消息是否有内容
        const msgIsNotEmpty = !!(msg.data?.content?.text) || !!(msg.data?.errorMsg);
        this.flag = msg.flag;
        this.role = msg.data.role;

        const role = this.role;
        const showAvatar = this.chatInstance.config.showAvatar;
        const avatar = this.role == 'user' ? this.chatInstance.config.userAvatar : this.chatInstance.config.assistantAvatar;
        this.shadowRoot.innerHTML = `
        <style>
            :host {
                display: block;
                margin-bottom: 1rem;
                position: relative;
                font-size: 16px;
            }
            .logo.custom-avatar {
                background-image: var(--avatar-url);
                background-size: cover;
                background-position: center;
                background-repeat: no-repeat;
            }

            .fragment {
                position: relative;
                overflow: hidden;
            }
        </style>
        <div class="ja_msg ${role}">
            ${(role == 'assistant' && showAvatar) ? `<div class="logo ${role}${avatar ? ' custom-avatar' : ''}" ${avatar ? `style="--avatar-url: url('${avatar}')"` : ''}></div>` : ''}
            <div class="container_wrapper ${role}">
                <div class="container">
                    ${msgIsNotEmpty ? '' : `
                        <div class="start_tip">
                            <span>AI正在思考中</span>
                            <div class="dots">
                                <span></span>
                                <span></span>
                                <span></span>
                            </div>
                        </div>
                    `}
                    ${role == 'assistant' ? `
                        <div class="thinking" style="display: none;">
                            <div class="thinking-controls">
                                <button class="thinking-toggle">
                                    <div class="thinking-toggle-text">展开思考过程</div>
                                    <span class="thinking-duration"></span>
                                    <svg class="thinking-toggle-icon" viewBox="0 0 24 24" width="16" height="16">
                                        <path fill="currentColor" d="M7.41 8.59L12 13.17l4.59-4.58L18 10l-6 6-6-6 1.41-1.41z"></path>
                                    </svg>
                                </button>
                            </div>
                            <div class="thinking-content" style="display: none;"></div>
                        </div>
                    ` : ''}

                    <div class="fragment"></div>
                </div>
                <div class="msg-tips-${role}">
                     <div class="msg-tips-box hide">
                           <div id="time">${msg.createTime?.substring(0, 16)}</div>
                           <div>
                              AI生成,仅供参考
                           </div>
                     </div>
                </div>

                ${role == 'assistant' ? `
                <div style="margin-top:0.375rem">
                       <!-- 自定义删除对话框 -->
                   <div id="confirmationModal" class="modal">
                        <div class="modal-content">
                            <p>
                            <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path fill="#F0A122FF" d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10s10-4.48 10-10S17.52 2 12 2m1 15h-2v-2h2zm0-4h-2V7h2z"/></svg>
                            &nbsp;确认删除该记录？</p>
                            <button id="confirmDelete">确定</button>
                            <button id="cancelDelete">取消</button>
                        </div>
                    </div>
                    <!-- 自定义复制成功提示框-->
                    <div id="notif" class="notification">
                         <div class="notif-box">
                                <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="-2 -2 24 24"><path fill="rgb(24 160 88)" d="M10 20C4.477 20 0 15.523 0 10S4.477 0 10 0s10 4.477 10 10s-4.477 10-10 10m0-2a8 8 0 1 0 0-16a8 8 0 0 0 0 16m0-6.172l3.536-3.535a1 1 0 0 1 1.414 1.414l-4.243 4.243a1 1 0 0 1-1.414 0L5.05 9.707a1 1 0 0 1 1.414-1.414z" strokeWidth={2} stroke="rgb(24 160 88)"></path></svg>
                                </jb-icon>&nbsp;&nbsp;复制成功!
                         </div>
                    </div>
                    ${this.generateActionButtons()}
                </div>

                ` : ''}

                <div class="refers hide">
                    <div class="refers_header">
                        <span class="refers_label">参考资料</span> <span class="refers_count">- 5</span>
                        <svg fill="#6B7280" class="refers_btn" viewBox="0 0 1394 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2619" width="10" height="10"><path d="M808.665066 968.123525a139.174837 139.174837 0 0 1-222.989114 0L28.061551 224.448838A140.525626 140.525626 0 0 1 0 140.133462C0 62.746326 62.484883 0 139.567002 0h1115.228801c30.283817 0 59.739731 9.891261 83.944998 28.192273 61.569833 46.558646 73.901229 134.425289 27.538666 196.256565L808.665066 968.123525z"  p-id="2620"></path></svg>
                    </div>
                    <div class="refers_list"></div>
                </div>
                ${role == 'assistant'?`<div class="resizer"></div>`:''}
            </div>
            ${(role == 'user' && showAvatar) ? `<div class="logo ${role}${avatar ? ' custom-avatar' : ''}" ${avatar ? `style="--avatar-url: url('${avatar}');background-color:transparent  !important"` : ''}></div>` : ''}
        </div>
    `;
        this.container = this.shadowRoot.querySelector('.container');
        this.fragment = this.container.querySelector('.fragment');
        this.refers = this.shadowRoot.querySelector('.refers');
        this.messageActions = this.shadowRoot.querySelector(".message-actions");
        this.appendMsg(msg)
        this.renderMsg();
        if (msg.data.reference) {
            this.renderReference(msg.data.reference)
        }

        this.registerActionEvents()
    }
}

export default ChatMessage